package cn.ryanpenn.game.tetris.game;

import cn.ryanpenn.game.tetris.model.Client;
import cn.ryanpenn.game.tetris.model.Square;
import cn.ryanpenn.game.tetris.repository.PlayerRepository;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * MessageEventHandler
 *
 * @author pennryan
 */
@Component
public class MessageEventHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    SocketIOServer server;

    @Autowired
    PlayerRepository playerRepository;

    private static final int CLIENT_SIZE = 2;
    private Map<String, Client> group = new HashMap<>(CLIENT_SIZE);

    /**
     * 客户端发起连接时处理connect事件
     *
     * @param client 客户端
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        String name = client.getHandshakeData().getSingleUrlParam("name");
        String uuidStr = client.getSessionId().toString();
        group.put(uuidStr, new Client(uuidStr, client));
        logger.info("客户端登录: {} - {}", name, uuidStr);
    }

    /**
     * 客户端断开连接时,处理disconnect事件
     *
     * @param client 客户端
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        String name = client.getHandshakeData().getSingleUrlParam("name");
        String uuidStr = client.getSessionId().toString();
        if (group.containsKey(uuidStr)) {
            group.remove(uuidStr);
            if (group.size() >= 1) {
                group.forEach((k, v) -> {
                    v.getIo().sendEvent("leave", "");
                });
            }
        }

        logger.info("客户端断开: {} - {}", name, uuidStr);
    }

    //消息接收入口，当接收到消息后，查找发送目标客户端，并且向该客户端发送消息，且给自己发送消息

    /**
     * 收到客户端消息,处理特定事件:
     * socket.emit('event',{});
     *
     * @param client
     * @param request
     * @param data
     */
    @OnEvent(value = "start")
    public void start(SocketIOClient client, AckRequest request, Square data) {
        logger.info("收到客户端消息: start {}", data);

        String uuid = client.getSessionId().toString();
        if (group.size() < CLIENT_SIZE) {
            logger.info("此时玩家为P1.");
            client.sendEvent("wait", data);
            group.get(uuid).setData(data);
        } else if (group.size() == CLIENT_SIZE) {
            logger.info("此时玩家为P2.");
            Square sq = null;
            SocketIOClient p1 = null;
            for (String k : group.keySet()) {
                if (!StringUtils.equalsAnyIgnoreCase(k, uuid)) {
                    sq = group.get(k).getData();
                    p1 = group.get(k).getIo();
                    break;
                }
            }
            if (sq != null) {
                client.sendEvent("start", sq);
                p1.sendEvent("start", data);
            }
        } else {
            logger.info("玩家人数过多.");
        }
    }

    @OnEvent(value = "next")
    public void next(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("next", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "rotate")
    public void rotate(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("rotate", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "right")
    public void right(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("right", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "down")
    public void down(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("down", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "left")
    public void left(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("left", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "fall")
    public void fall(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("fall", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "fixed")
    public void fixed(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("fixed", client.getSessionId().toString(), data);
    }

    @OnEvent(value = "over")
    public void over(SocketIOClient client, AckRequest request, Object data) {
        forwardMessage("over", client.getSessionId().toString(), data);
    }

    /**
     * 将消息转发给对方
     *
     * @param event 事件名称
     * @param uuid  uuid
     * @param data  数据
     */
    private void forwardMessage(String event, String uuid, Object data) {
        logger.info("客户端({}): {}", uuid, event);
        group.values().forEach((v) -> {
            if (!StringUtils.equalsAnyIgnoreCase(v.getUuid(), uuid)) {
                v.getIo().sendEvent(event, data);
            }
        });
    }
}
